#pragma once

#include <iostream>
#include <string>
#include <memory>
#include "Socket.hpp"
#include "TcpServer.hpp"
#include <jsoncpp/json/json.h>
#include <functional>

//为避免报文不完整，在json串前加一个长度，表示有效载荷的长度。中间加一个\r\n，尾部也加一个\r\n

class Request
{
public:
    Request(){}
    Request(int x, int y, char op) :_x(x), _y(y), _op(op)
    {}

    int X() const { return _x; }
    int Y() const { return _y; }
    int OP() const {return _op; }

    //序列化
    std::string Serialize()
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["op"] = _op;

        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }

    //反序列化
    bool Deserialize(std::string& in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if(ok)
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _op = root["op"].asInt();
        }
        return ok;
    }
private:
    int _x, _y;
    char _op;
};

class Response
{
public:
    Response(){}
    Response(int ret, int code = 0) :_ret(ret), _code(code) {}
    
    void SetRet(int ret)
    {
        _ret = ret;
    }

    void SetCode(int code)
    {
        _code = code;
    }

    void ShowResult()
    {
        if(_code == 1) std::cout << "除0错误" << std::endl;
        else if(_code == 2) std::cout << "余0错误" << std::endl;
        else if(_code == 3) std::cout << "非法操作" << std::endl;
        else std::cout << "结果是：" << _ret << std::endl;
    }

    //序列化
    std::string Serialize()
    {
        Json::Value root;
        root["ret"] = _ret;
        root["code"] = _code;

        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }

    //反序列化
    bool Deserialize(std::string& in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if(ok)
        {
            _ret = root["ret"].asInt();
            _code = root["code"].asInt();
        }
        return ok;
    }
private:
    int _ret;
    int _code; // 结果的状态，表示是否成功计算
};

const std::string sep = "\r\n";

typedef std::function<Response(const Request&)> func_t;

class Protocol
{
public:
    Protocol(func_t func) : _func(func)
    {}

    Protocol() = default;

    //添加报头
    std::string Encode(const std::string& jsonstr)
    {
        std::string len = std::to_string(jsonstr.size());
        return len + sep + jsonstr + sep;
    }

    //报文解析，分解出有效载荷
    bool Decode(std::string& buffer, std::string& package)
    {
        int pos = buffer.find(sep);
        if(pos == std::string::npos) return false;

        //走到这，说明至少读到了有效载荷的长度
        std::string package_len_str = buffer.substr(0, pos);
        int package_len_int = stoi(package_len_str);
        int target_len = package_len_str.size() + 2 * sep.size() + package_len_int;
        if(buffer.size() < target_len) return false;

        //走到这，说明至少读到一个完整的报文
        package = buffer.substr(pos + sep.size(), package_len_int); // 读出报文的json串
        buffer.erase(0, target_len); // buffer中删除完整报文
        return true;
    }

    //服务器获取请求并应答
    void GetRequest(std::shared_ptr<Socket>& sock, InetAddr& client)
    {
        std::string buffer_queue;
        while(true)
        {
            //收消息
            int n = sock->Recv(buffer_queue);
            if(n > 0)
            {
                //解析报文，分离出有效载荷
                std::string package;
                while(Decode(buffer_queue, package))
                {
                    //此时保证一定读取到一个完整有效载荷 -- 是一个json序列
                    //反序列化
                    Request req;
                    req.Deserialize(package);
                    
                    //业务处理
                    Response rep = _func(req);

                    //序列化
                    std::string json_str = rep.Serialize();

                    //添加报头
                    std::string send_str = Encode(json_str);

                    //应答
                    sock->Send(send_str);
                }
            }
            else if(n == 0)
            {
                LOG(LogLevel::INFO) << client.StringAddr() << "退出了";
                break;
            }
            else
            {
                LOG(LogLevel::WARING) << client.StringAddr() << "读取错误";
                break;
            }
        }
    }

    //客户端构建请求
    std::string BuildRequest(int x, int y, char op)
    {
        //构建结构化数据
        Request req(x, y, op);

        //序列化
        std::string json_req = req.Serialize();

        //添加报头
        std::string send_str = Encode(json_req);
        return send_str;
    }

    //客户端获取应答
    bool GetResponse(std::shared_ptr<Socket>& client, std::string& buff, Response& rep)
    {
        while(true)
        {
            int n = client->Recv(buff);
            if(n > 0)
            {
                //解析报文
                std::string json_str;
                while(Decode(buff, json_str))
                {
                    //反序列化
                    rep.Deserialize(json_str);
                    return true;
                }
            }
            else if(n == 0)
            {
                std::cerr << "server quit" << std::endl;
                return false;
            }
            else
            {
                std::cerr << "recv error" << std::endl;
                return false;
            }
        }
    }
private:
    func_t _func;
};